package lolic;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.LayoutManager;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Properties;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingConstants;
import javax.swing.TransferHandler;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * This class contains the GUI layout of the Lolic application
 * @author Dave DePiano
 *
 */

public class GUI
{
	static JFrame frame = new JFrame("lolic"); 
	Document docItems;
	Document docChamps;
	Document docSettings;
	int intItemSize;
	int intChampSize;
	static Java2sAutoComboBox acmpItems;
	static Java2sAutoComboBox acmpChamps;
	JLabel lblItemPortrait = new JLabel();
	JLabel lblChampPortrait;
	static JTextField txtBrowse = new JTextField();
	static JLabel lblItem1 = new JLabel();
	static JLabel lblItem2 = new JLabel();
	static JLabel lblItem3 = new JLabel();
	static JLabel lblItem4 = new JLabel();
	static JLabel lblItem5 = new JLabel();
	static JLabel lblItem6 = new JLabel();
	Element eleLolPath;
	static JComboBox cmbGameType;
	static JButton btnSave;
	static Champ currentChamp;

	public GUI()
	{	
		readDocuments();
		createAndShowGUI();
	}	
	
	public static void packFrame()
	{
		frame.pack();
	}

	private void readDocuments()
	{
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder dbChamps;
		DocumentBuilder dbItems;
		DocumentBuilder dbSettings;

		try {
			dbChamps = dbf.newDocumentBuilder();
			dbItems = dbf.newDocumentBuilder();
			dbSettings = dbf.newDocumentBuilder();
			//read the XML documents from the web
			docChamps = dbChamps.parse(new URL(Statics.strChampsURL).openStream());
			//docChamps = dbChamps.parse("champs.xml"); //just for internal testing
			intChampSize = docChamps.getDocumentElement().getElementsByTagName("Champ").getLength();
			docItems = dbItems.parse  (new URL(Statics.strItemsURL ).openStream());
			//docItems = dbItems.parse  ("items.xml"); //just for internal testing
			intItemSize = docItems.getDocumentElement().getElementsByTagName("Item").getLength();
			//read the local settings.xml file for local settings (should have probably used the Preferences class)
			docSettings = dbSettings.parse("settings.xml");
			
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void writeXML(Document doc, String strFilename)
	{

		try {
			Transformer transformer = TransformerFactory.newInstance().newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			//initialize StreamResult with File object to save to file
			StreamResult result = new StreamResult(new StringWriter());
			DOMSource source = new DOMSource(doc);
			transformer.transform(source, result);
			String xmlString = result.getWriter().toString();
			FileWriter fstream = new FileWriter(strFilename);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(xmlString);
			out.close();
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


	}

	private void createAndShowGUI() 
	{        
		customizeFrame(frame);

		//setup the main panel
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout((LayoutManager) new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

		//setup browse panel
		JPanel pnlBrowse = generaterateBrowsePanel();    

		//setup the items progress bar and populate the items list
		JProgressBar pgbItems = generateItemProgressPopup();
		PopupFactory factory = PopupFactory.getSharedInstance();
		Popup popup = factory.getPopup(pgbItems, pgbItems, 200, 250);
		popup.show();	
		populateItemsList(pgbItems, docItems);        
		
		//setup the champs progress bar and populate the champs list
		JProgressBar pgbChamps = generateChampProgressPopup();
		Popup popup2 = factory.getPopup(pgbChamps, pgbChamps, 200, 200);
		popup2.show();		
		populateChampsList(pgbChamps, docChamps);
		
		//hide the progress bars
		popup.hide();
		popup2.hide();

		frame.getContentPane().add(mainPanel);
		frame.setVisible(true);

		//initialize the items on the GUI
		lblItemPortrait = new JLabel(new ImageIcon("blank.gif"));
		customizeChampPortrait();
		JPanel pnlChampSelection = generateChampSelection();
		JPanel pnlItemSelection = generateItemSelection();

		acmpItems.addActionListener(new AcmpItemsActionListener());
		acmpChamps.addActionListener(new AcmpChampsActionListener());
		
		JPanel pnlItemInventory = generateInventoryItems();    
		
		generateSaveButton();

		mainPanel.add(pnlBrowse);
		mainPanel.add(pnlChampSelection);
		mainPanel.add(pnlItemSelection);
		mainPanel.add(pnlItemInventory);       
		mainPanel.add(btnSave);
		mainPanel.add(Box.createVerticalGlue());

		frame.getContentPane().add(mainPanel);
		frame.pack();
		
		frame.setVisible(true);
	}

	private void generateSaveButton() {
		btnSave = new JButton("Save");
		btnSave.setSize(100, 60);
		btnSave.addActionListener(new BtnSaveActionListener());
		btnSave.setEnabled(false);
		btnSave.setBorder(BorderFactory.createEmptyBorder(10, 50, 10, 50));
	}

	private JPanel generateChampSelection() 
	{
		JPanel pnlChampSelection = new JPanel();
		pnlChampSelection.add(lblChampPortrait);
		pnlChampSelection.add(acmpChamps);
		pnlChampSelection.setBorder(BorderFactory.createEmptyBorder(10, 50, 10, 50));
		
		String[] gameTypes = { "Classic", "Dominion" };
		cmbGameType = new JComboBox(gameTypes);		
		pnlChampSelection.add(cmbGameType);
		
		JLabel lblHelp = new JLabel();
		lblHelp.setIcon(new ImageIcon("help.png"));
		lblHelp.addMouseListener(new MouseListener(){

			public void mouseClicked(MouseEvent e) {}
			public void mousePressed(MouseEvent e) {
				System.out.println("Hey");
				String instructions = "<html>" +
						"<ol>" +
						"<li>  Browse to your \"Riot Games\" directory  (Probably in C:\\Riot Games or C:\\Program Files)." +
						"<li>  Select the champion you want to customize and the gametype you want to change your items for" +
						"<li>  Select an item you want to use and drag the icon's icon to an inventory slot.  Repeat this step for each inventory slot" +
						"<li>  Save the new inventory by clicking on the save button" +
						"<li>  Run the game and enjoy your new recommended item inventory" +
						"</ol>" +
						"<p> Note that you won't have to run this utility before starting LOL every time.  Your changes will be saved.</p>" +
						"</html>";
						
				JOptionPane.showMessageDialog(frame, instructions, "Instructions", JOptionPane.INFORMATION_MESSAGE);
				/*
				 * 1)  Browse to your "Riot Games" directory  (Probably in C:\Riot Games or C:\Program Files).
				 * 2)  Select the champion you want to customize and the gametype you want to change your items for
				 * 3)  Select an item you want to use and drag the icon's icon to an inventory slot.  Repeat this step for each inventory slot
				 * 4)  Save the new inventory by clicking on the save button
				 * 
				 * 
				 * 
				 */
				//.showInternalMessageDialog(frame, "information","information", JOptionPane.INFORMATION_MESSAGE);				
			}
			public void mouseReleased(MouseEvent e) {}
			public void mouseEntered(MouseEvent e) {}
			public void mouseExited(MouseEvent e) {}
			
		});
		pnlChampSelection.add(lblHelp);
		return pnlChampSelection;
	}

	private JPanel generateItemSelection() {
		JPanel pnlItemSelection = new JPanel();
		pnlItemSelection.add(lblItemPortrait);
		pnlItemSelection.add(acmpItems);
		pnlItemSelection.setBorder(BorderFactory.createEmptyBorder(10, 50, 10, 50));
		return pnlItemSelection;
	}

	private void customizeFrame(JFrame frame) 
	{
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(500, 500);
		//set the location of the main frame
		Toolkit tk = Toolkit.getDefaultToolkit();
		Dimension screenSize = tk.getScreenSize();
		int screenHeight = screenSize.height;
		int screenWidth = screenSize.width;
		frame.setLocation(screenWidth / 4, screenHeight / 4);
	}

	private JPanel generateInventoryItems() {
		JPanel pnlItems = new JPanel();
		pnlItems.setLayout((LayoutManager) new BoxLayout(pnlItems, BoxLayout.X_AXIS));
		//should do this in a loop
		pnlItems.add(lblItem1);
		lblItem1.setIcon(new ImageIcon("blank.png"));
		lblItem1.setBorder(BorderFactory.createEmptyBorder(0,0,50,50));
		pnlItems.add(lblItem2);
		lblItem2.setIcon(new ImageIcon("blank.png"));
		lblItem2.setBorder(BorderFactory.createEmptyBorder(0,0,50,50));
		pnlItems.add(lblItem3);
		lblItem3.setIcon(new ImageIcon("blank.png"));
		lblItem3.setBorder(BorderFactory.createEmptyBorder(0,0,50,50));
		pnlItems.add(lblItem4);
		lblItem4.setIcon(new ImageIcon("blank.png"));
		lblItem4.setBorder(BorderFactory.createEmptyBorder(0,0,50,50));
		pnlItems.add(lblItem5);
		lblItem5.setIcon(new ImageIcon("blank.png"));
		lblItem5.setBorder(BorderFactory.createEmptyBorder(0,0,50,50));
		pnlItems.add(lblItem6);
		lblItem6.setIcon(new ImageIcon("blank.png"));
		lblItem6.setBorder(BorderFactory.createEmptyBorder(0,0,50,50));
		pnlItems.setBorder(BorderFactory.createEmptyBorder(10, 50, 0, 50));
		lblItem1.setFont(new Font("Arial", Font.PLAIN, 10));

		//get ready for drag n drop
		LblItemSlotTransferHandler t = new LblItemSlotTransferHandler(acmpItems.getDataList());

		lblItem1.setTransferHandler(t);
		lblItem2.setTransferHandler(t);
		lblItem3.setTransferHandler(t);
		lblItem4.setTransferHandler(t);
		lblItem5.setTransferHandler(t);
		lblItem6.setTransferHandler(t);
		
		lblItem1.setHorizontalTextPosition(SwingConstants.CENTER);
		lblItem1.setVerticalTextPosition(SwingConstants.BOTTOM);
		lblItem2.setHorizontalTextPosition(SwingConstants.CENTER);
		lblItem2.setVerticalTextPosition(SwingConstants.BOTTOM);
		lblItem3.setHorizontalTextPosition(SwingConstants.CENTER);
		lblItem3.setVerticalTextPosition(SwingConstants.BOTTOM);
		lblItem4.setHorizontalTextPosition(SwingConstants.CENTER);
		lblItem4.setVerticalTextPosition(SwingConstants.BOTTOM);
		lblItem5.setHorizontalTextPosition(SwingConstants.CENTER);
		lblItem5.setVerticalTextPosition(SwingConstants.BOTTOM);
		lblItem6.setHorizontalTextPosition(SwingConstants.CENTER);
		lblItem6.setVerticalTextPosition(SwingConstants.BOTTOM);
		return pnlItems;
	}

	private void customizeChampPortrait() {
		lblChampPortrait = new JLabel(new ImageIcon("blank.png"));        
		lblItemPortrait.setTransferHandler(new TransferHandler("text"));
		lblItemPortrait.addMouseListener(new lblItemPortraitMouseListener());
	}

	private JProgressBar generateChampProgressPopup() {
		JProgressBar pgbChamps = new JProgressBar(0, intChampSize);
		pgbChamps.setValue(0);
		pgbChamps.setString("Populating Champ List");
		pgbChamps.setStringPainted(true);
		return pgbChamps;
	}

	private JProgressBar generateItemProgressPopup() {
		JProgressBar pgbItems;
		pgbItems = new JProgressBar(0, intItemSize);
		pgbItems.setString("Populating Item List");
		pgbItems.setValue(0);
		pgbItems.setStringPainted(true);
		return pgbItems;
	}

	private JPanel generaterateBrowsePanel() {
		JButton btnBrowse = new JButton("Browse...");
		btnBrowse.addActionListener(new btnBrowseActionListener());
		JPanel pnlBrowse = new JPanel();
		pnlBrowse.setLayout(new BoxLayout(pnlBrowse, BoxLayout.X_AXIS));

		docSettings.getDocumentElement ().normalize ();  
		NodeList nlSettings = docSettings.getElementsByTagName("setting");
		System.out.println(nlSettings.getLength());
		int i = 0;
		boolean found = false;
		while(i < nlSettings.getLength() && found == false)
		{
			Element e = (Element)nlSettings.item(i);
			System.out.println(e.getAttribute("name"));
			String strSetting = e.getAttribute("name");

			if(strSetting.compareTo("lolPath") == 0) //the string values are equal
			{
				eleLolPath = e;
				txtBrowse.setText(eleLolPath.getAttribute("path"));
			}      
			i++;
		}
		pnlBrowse.add(btnBrowse);
		pnlBrowse.add(Box.createRigidArea(new Dimension(5,0)));
		pnlBrowse.setMaximumSize(new Dimension(1000,40));
		pnlBrowse.add(txtBrowse);

		return pnlBrowse;
	}

	private void populateItemsList(JProgressBar progressBar, Document docItems)
	{
		ItemCollector items = new ItemCollector(progressBar, docItems);
		acmpItems = new Java2sAutoComboBox(items);
		acmpItems.setMaximumSize(new Dimension(1000,40));
	}

	private void populateChampsList(JProgressBar progressBar, Document docChamps)
	{
		ChampCollector champs = new ChampCollector(progressBar, docChamps);
		acmpChamps = new Java2sAutoComboBox(champs);
		acmpChamps.setMaximumSize(new Dimension(1000,40));
	}




	public class AcmpItemsActionListener implements ActionListener
	{

		public void actionPerformed(ActionEvent e) //called when an item is selected
		{
			Java2sAutoComboBox acmpItems = (Java2sAutoComboBox)e.getSource();
			List list = acmpItems.getDataList();
			try {
				System.out.println(acmpItems.getSelectedItem().toString());
				Item item = Item.getMatchingItem(acmpItems.getSelectedItem().toString(), list);
				lblItemPortrait.setIcon(item.getImgPortrait());
				System.out.println(item.getImgPortrait().getDescription());
				lblItemPortrait.setText(item.getStrName());
				lblItemPortrait.setHorizontalTextPosition(SwingConstants.CENTER);
				lblItemPortrait.setVerticalTextPosition(SwingConstants.BOTTOM);
			} catch (Exception e2)
			{
				e2.printStackTrace();
			}
		}
	}

	public class AcmpChampsActionListener implements ActionListener
	{

		public void actionPerformed(ActionEvent e) 
		{
			Java2sAutoComboBox acmpItems = (Java2sAutoComboBox)e.getSource();
			List list = acmpItems.getDataList();
			System.out.println(acmpItems.getSelectedItem());
			Champ champ = getMatchingChamp(acmpItems.getSelectedItem().toString(), list);
			lblChampPortrait.setIcon(champ.getImgPortrait());
			loadInventory(champ);
			currentChamp = champ;
			btnSave.setEnabled(true);
			btnSave.setBackground(Color.GREEN);
			btnSave.setOpaque(true);

			
		}
		
		public void loadInventory(Champ champ)
		{
			//go to the correct folder
			File fBasePath = new File(txtBrowse.getText());
			
			//C:\Riot Games\League of Legends\RADS\solutions\lol_game_client_sln\releases\0.0.0.75\deploy\DATA
			
			File fIniFile = Item.getIniFile(champ, fBasePath);
			if(fIniFile.exists()) //there's a pre-existing ini file to read to load the inventory
			{
				System.out.println("reading");
				readIniFile(fIniFile);
			}
			else //clear the inventory
			{
				clearInventory();
			}
		}
		
		private void clearInventory()
		{
			ImageIcon imgBlank = new ImageIcon("blank.gif");
			lblItem1.setIcon(imgBlank);
			lblItem1.setToolTipText("");
			lblItem2.setIcon(imgBlank);
			lblItem2.setToolTipText("");
			lblItem3.setIcon(imgBlank);
			lblItem3.setToolTipText("");
			lblItem4.setIcon(imgBlank);
			lblItem4.setToolTipText("");
			lblItem5.setIcon(imgBlank);
			lblItem5.setToolTipText("");
			lblItem6.setIcon(imgBlank);
			lblItem6.setToolTipText("");
		}
		
		private void readIniFile(File fIniFile)
		{
			 Properties p = new Properties();
		     try {
				p.load(new FileInputStream(fIniFile));
				
				System.out.println(p.getProperty("RecItem1"));
				Item item = Item.getMatchingItem(p.getProperty("RecItem1"), acmpItems.getDataList());
				lblItem1.setIcon(item.getImgPortrait());
				lblItem1.setToolTipText(item.getStrName());
				
				item = Item.getMatchingItem(p.getProperty("RecItem2"), acmpItems.getDataList());
				lblItem2.setIcon(item.getImgPortrait());
				lblItem2.setToolTipText(item.getStrName());
				
				item = Item.getMatchingItem(p.getProperty("RecItem3"), acmpItems.getDataList());
				lblItem3.setIcon(item.getImgPortrait());
				lblItem3.setToolTipText(item.getStrName());
				
				item = Item.getMatchingItem(p.getProperty("RecItem4"), acmpItems.getDataList());
				lblItem4.setIcon(item.getImgPortrait());
				lblItem4.setToolTipText(item.getStrName());
				
				item = Item.getMatchingItem(p.getProperty("RecItem5"), acmpItems.getDataList());
				lblItem5.setIcon(item.getImgPortrait());
				lblItem5.setToolTipText(item.getStrName());
				
				item = Item.getMatchingItem(p.getProperty("RecItem6"), acmpItems.getDataList());
				lblItem6.setIcon(item.getImgPortrait());
				lblItem6.setToolTipText(item.getStrName());
				
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

		

		public Champ getMatchingChamp(String strItem, List list)
		{
			boolean found = false;
			int i = 0;
			while(found == false && i < list.size())
			{
				Champ champ = (Champ)list.get(i);
				if(champ.getStrName() == strItem)
				{
					found = true;
					return champ;
				}
				i++;
			}
			return null;
		}
	}

	public class btnBrowseActionListener implements ActionListener
	{

		public void actionPerformed(ActionEvent e) 
		{			   
			JFileChooser chooser = new JFileChooser();
			chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			chooser.setDialogTitle("Point to the Riot Games Directory");

			//C:\Riot Games\League of Legends\RADS\solutions\lol_game_client_sln\releases\x.x.x.x\deploy\DATA

			int returnVal = chooser.showOpenDialog(null);
			if(returnVal == JFileChooser.APPROVE_OPTION) 
			{
				String strPath = chooser.getSelectedFile().getAbsolutePath();
				txtBrowse.setText(strPath);
				eleLolPath.setAttribute("path", strPath);
				writeXML(docSettings, "settings.xml");
			}
		}

	}

	public class lblItemPortraitMouseListener implements MouseListener
	{

		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub

		}

		public void mousePressed(MouseEvent e) {
			JComponent comp = (JComponent)e.getSource();
			TransferHandler th = comp.getTransferHandler();
			// Start the drag operation
			th.exportAsDrag(comp, e, TransferHandler.COPY);

		}

		public void mouseReleased(MouseEvent e) {
			// TODO Auto-generated method stub

		}

		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub

		}

		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub

		}

	}
	
	

}
